package znet

import (
	"fmt"
	"my-zinx/lib"
	"my-zinx/utils"
	"my-zinx/ziface"
	"net"
	"time"
)

// Server 服务类
type Server struct {
	Name        string
	IPVersion   string // tcp4 or other
	IP          string
	Port        int
	msgHandler  ziface.IMsgHandle   // 支持多路由消息处理
	ConnMgr     ziface.IConnManager // 连接管理
	OnConnStart func(conn ziface.IConnection)
	OnConnStop  func(conn ziface.IConnection)
}

// NewServer 创建一个Server
func NewServer() ziface.IServer {
	utils.Env.Reload()

	return &Server{
		Name:       utils.Env.Name,
		IPVersion:  "tcp4",
		IP:         utils.Env.Host,
		Port:       utils.Env.Port,
		msgHandler: NewMsgHandle(),
		ConnMgr:    NewConnManager(),
	}
}

func NewPackedMsg(id uint64, msg string) []byte {
	dp := NewDataPack()
	packed, _ := dp.Pack(NewMessage(id, []byte(msg)))
	return packed
}

// Start 启动服务
func (s *Server) Start() {
	fmt.Printf("[START] Server listener at IP:%s, Port:%d is starting\n", s.IP, s.Port)

	// 开启一个goroutine去listener业务
	go func() {
		// 启动池子
		s.msgHandler.StartWorkerPool()

		// 获取tcp addr
		address := fmt.Sprintf("%s:%d", s.IP, s.Port)
		addr, err := net.ResolveTCPAddr(s.IPVersion, address)
		if err != nil {
			fmt.Println("resolve tcp addr err: ", err)
			return
		}

		// 监听服务器
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen tcp err: ", err)
			return
		}

		fmt.Printf("start zinx server success, %s, %s, now listening...\n", s.Name, utils.Env.Version)

		// 自动生成一个ID
		var connID uint64

		// 启动server网络连接业务
		for {
			// 等待客户端建立连接请求
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("accept err: ", err)
				return
			}

			// 设置服务器最大连接控制
			if s.ConnMgr.Len() >= utils.Env.MaxConn {
				_, _ = conn.Write(NewPackedMsg(500, "server is busy, please try again later\n"))
				_ = conn.Close()
				continue
			}

			// TODO 处理新连接请求的业务方法

			// XXX 回显服务
			connID = lib.NextID()
			dealConn := NewConnection(s, conn, connID, s.msgHandler)

			fmt.Printf("[Manager] current connections: %d, max connections: %d\n", s.ConnMgr.Len(), utils.Env.MaxConn)

			go dealConn.Start()
		}
	}()
}

// Stop 停止服务
func (s *Server) Stop() {
	fmt.Printf("[STOP] zinx server, %s, is stop\n", s.Name)

	// 清理连接信息
	s.ConnMgr.ClearConn()
}

// Serve 开启业务服务
func (s *Server) Serve() {
	s.Start()

	// TODO 启动服务，处理其他事情

	for {
		time.Sleep(10 * time.Second)
	}
}

func (s *Server) AddRouter(msgID uint64, router ziface.IRouter) {
	s.msgHandler.AddRouter(msgID, router)
}

func (s *Server) GetConnMgr() ziface.IConnManager {
	return s.ConnMgr
}

func (s *Server) SetOnConnStart(f func(conn ziface.IConnection)) {
	s.OnConnStart = f
}

func (s *Server) SetOnConnStop(f func(conn ziface.IConnection)) {
	s.OnConnStop = f
}

func (s *Server) CallOnConnStart(conn ziface.IConnection) {
	if s.OnConnStart != nil {
		s.OnConnStart(conn)
	}
}

func (s *Server) CallOnConnStop(conn ziface.IConnection) {
	if s.OnConnStop != nil {
		s.OnConnStop(conn)
	}
}
